// Copyright (c) 2020 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0 or MIT

use codec::{Codec, EncodeErr};
use core::convert::TryFrom;

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub enum SpdmVersion {
    SpdmVersion10,
    SpdmVersion11,
    SpdmVersion12,
}

impl Default for SpdmVersion {
    fn default() -> Self {
        Self::SpdmVersion10
    }
}

impl TryFrom<u8> for SpdmVersion {
    type Error = ();
    fn try_from(untrusted_spdm_version: u8) -> Result<Self, <Self as TryFrom<u8>>::Error> {
        if untrusted_spdm_version == 0x10 {
            Ok(SpdmVersion::SpdmVersion10)
        } else if untrusted_spdm_version == 0x11 {
            Ok(SpdmVersion::SpdmVersion11)
        } else if untrusted_spdm_version == 0x12 {
            Ok(SpdmVersion::SpdmVersion12)
        } else {
            Err(())
        }
    }
}

impl From<SpdmVersion> for u8 {
    fn from(spdm_version: SpdmVersion) -> Self {
        match spdm_version {
            SpdmVersion::SpdmVersion10 => 0x10,
            SpdmVersion::SpdmVersion11 => 0x11,
            SpdmVersion::SpdmVersion12 => 0x12,
        }
    }
}

impl From<&SpdmVersion> for u8 {
    fn from(spdm_version: &SpdmVersion) -> Self {
        u8::from(*spdm_version)
    }
}

impl Codec for SpdmVersion {
    fn encode(&self, bytes: &mut codec::Writer<'_>) -> Result<usize, EncodeErr> {
        u8::from(self).encode(bytes)
    }

    fn read(r: &mut codec::Reader<'_>) -> Option<Self> {
        let spdm_version = u8::read(r)?;
        Self::try_from(spdm_version).ok()
    }
}

pub const MAX_SPDM_VERSION_COUNT: usize = 3;

//SPDM V1.2 signing prefix context
pub const SPDM_VERSION_1_2_SIGNING_PREFIX_CONTEXT: [u8; 64] = [
    0x64, 0x6d, 0x74, 0x66, 0x2d, 0x73, 0x70, 0x64, 0x6d, 0x2d, 0x76, 0x31, 0x2e, 0x32, 0x2e, 0x2a,
    0x64, 0x6d, 0x74, 0x66, 0x2d, 0x73, 0x70, 0x64, 0x6d, 0x2d, 0x76, 0x31, 0x2e, 0x32, 0x2e, 0x2a,
    0x64, 0x6d, 0x74, 0x66, 0x2d, 0x73, 0x70, 0x64, 0x6d, 0x2d, 0x76, 0x31, 0x2e, 0x32, 0x2e, 0x2a,
    0x64, 0x6d, 0x74, 0x66, 0x2d, 0x73, 0x70, 0x64, 0x6d, 0x2d, 0x76, 0x31, 0x2e, 0x32, 0x2e, 0x2a,
];
//"dmtf-spdm-v1.2.*dmtf-spdm-v1.2.*dmtf-spdm-v1.2.*dmtf-spdm-v1.2.*"
pub const SPDM_CHALLENGE_AUTH_SIGN_CONTEXT: [u8; 32] = [
    0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65,
    0x6e, 0x67, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67,
];
// "responder-challenge_auth signing"
pub const SPDM_MUT_CHALLENGE_AUTH_SIGN_CONTEXT: [u8; 32] = [
    0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2d, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65,
    0x6e, 0x67, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67,
];
// "requester-challenge_auth signing"
pub const SPDM_MEASUREMENTS_SIGN_CONTEXT: [u8; 30] = [
    0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x2d, 0x6d, 0x65, 0x61, 0x73, 0x75, 0x72,
    0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67,
];
// "responder-measurements signing"
pub const SPDM_KEY_EXCHANGE_RESPONSE_SIGN_CONTEXT: [u8; 34] = [
    0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x2d, 0x6b, 0x65, 0x79, 0x5f, 0x65, 0x78,
    0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x72, 0x73, 0x70, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x69,
    0x6e, 0x67,
];
// "responder-key_exchange_rsp signing"
pub const SPDM_VERSION_1_2_KEY_EXCHANGE_REQUESTER_CONTEXT: [u8; 28] = [
    0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2d, 0x4b, 0x45, 0x50, 0x2d, 0x64, 0x6d,
    0x74, 0x66, 0x2d, 0x73, 0x70, 0x64, 0x6d, 0x2d, 0x76, 0x31, 0x2e, 0x32,
];
// "Requester-KEP-dmtf-spdm-v1.2"
pub const SPDM_VERSION_1_2_KEY_EXCHANGE_RESPONDER_CONTEXT: [u8; 28] = [
    0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x2d, 0x4b, 0x45, 0x50, 0x2d, 0x64, 0x6d,
    0x74, 0x66, 0x2d, 0x73, 0x70, 0x64, 0x6d, 0x2d, 0x76, 0x31, 0x2e, 0x32,
];
// "Responder-KEP-dmtf-spdm-v1.2"
pub const SPDM_FINISH_SIGN_CONTEXT: [u8; 24] = [
    0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2d, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68,
    0x20, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67,
];
// "requester-finish signing"
pub const SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE: usize = 100;
pub const SPDM_VERSION_1_2_SIGNING_CONTEXT_ZEROPAD_2: [u8; 2] = [0x0, 0x0];
pub const SPDM_VERSION_1_2_SIGNING_CONTEXT_ZEROPAD_4: [u8; 4] = [0x0, 0x0, 0x0, 0x0];
pub const SPDM_VERSION_1_2_SIGNING_CONTEXT_ZEROPAD_6: [u8; 6] = [0x0, 0x0, 0x0, 0x0, 0x0, 0x0];
pub const SPDM_VERSION_1_2_SIGNING_CONTEXT_ZEROPAD_8: [u8; 8] =
    [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0];
pub const SPDM_VERSION_1_2_SIGNING_CONTEXT_ZEROPAD_12: [u8; 12] =
    [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0];
